home *** CD-ROM | disk | FTP | other *** search
- /*
- urlsnarf.c
-
- sniff the network for HTTP request URLs, output in CLF format.
- this is for demonstration purposes and educational use only.
-
- Copyright (c) 1999 Dug Song <dugsong@monkey.org>
- All rights reserved, all wrongs reversed.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
-
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- 3. The name of author may not be used to endorse or promote products
- derived from this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
- $Id: urlsnarf.c,v 1.23 2000/05/19 05:05:55 dugsong Exp $
- */
-
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <string.h>
- #include <time.h>
- #include <libnet.h>
- #include <nids.h>
- #include "base64.h"
-
- #include "version.h"
-
- /* Globals. */
- u_short Opt_dns = 1;
-
- void
- usage(void)
- {
- fprintf(stderr, "Usage: urlsnarf [-n] [-i interface]\n");
- exit(1);
- }
-
- /* Locate substring in a binary string. */
- u_char *
- bufbuf(u_char *big, int blen, u_char *little, int llen)
- {
- u_char *p;
-
- for (p = big; p <= big + blen - llen; p++) {
- if (memcmp(p, little, llen) == 0)
- return (p);
- }
- return (NULL);
- }
-
- /* XXX - blech. */
- char *
- get_request_time(void)
- {
- static char tstr[32], sign;
- struct tm *t, gmt;
- time_t tt = time(NULL);
- int days, hours, tz, len;
-
- gmt = *gmtime(&tt);
- t = localtime(&tt);
-
- days = t->tm_yday - gmt.tm_yday;
- hours = ((days < -1 ? 24 : 1 < days ? -24 : days * 24) +
- t->tm_hour - gmt.tm_hour);
- tz = hours * 60 + t->tm_min - gmt.tm_min;
-
- len = strftime(tstr, sizeof(tstr), "%e/%b/%Y:%X", t);
- if (len < 0 || len > sizeof(tstr) - 5)
- return (NULL);
-
- if (tz < 0) {
- sign = '-';
- tz = -tz;
- }
- else sign = '+';
-
- snprintf(tstr + len, sizeof(tstr) - len, " %c%.2d%.2d",
- sign, tz / 60, tz % 60);
-
- return (tstr);
- }
-
- int
- http_method_len(char *buf)
- {
- static char *methods[] = { "GET", "HEAD", "POST", "PUT", "DELETE",
- "TRACE", "CONNECT", NULL };
- char **pp;
- int i;
-
- for (pp = methods; *pp != NULL; pp++) {
- i = strlen(*pp);
- if (strncmp(buf, *pp, i) == 0)
- return (i);
- }
- return (0);
- }
-
- int
- process_http_request(struct tuple4 *addr, u_char *buf, int len)
- {
- char *p, *s, *e;
- char *method, *uri, *vhost, *reqtime, *user, *referer, *agent;
- int i, discard = 0;
-
- /* Process requests. */
- for (s = buf; (e = bufbuf(s, len, "\r\n\r\n", 4)) != NULL; s = e + 4) {
- i = (e + 4) - s;
- discard += i; len -= i;
- *e = '\0';
-
- method = uri = vhost = reqtime = user = referer = agent = NULL;
-
- /* Process header. */
- for (p = strtok(s, "\r\n"); p != NULL; p = strtok(NULL, "\r\n")) {
- if ((i = http_method_len(p)) != 0) {
- method = p;
- if (strlen(p) - i > 0) {
- p[i] = '\0';
- uri = p + i + 1;
- }
- }
- else if (strncasecmp(p, "Authorization: Basic ", 21) == 0) {
- p += 21;
- i = base64_pton(p, p, strlen(p));
- p[i] = '\0';
- user = p;
- if ((p = strchr(p, ':')) != NULL) *p = '\0';
- }
- else if (strncasecmp(p, "Host: ", 6) == 0)
- vhost = p + 6;
- else if (strncasecmp(p, "Referer: ", 9) == 0)
- referer = p + 9;
- else if (strncasecmp(p, "User-Agent: ", 12) == 0)
- agent = p + 12;
- }
- reqtime = get_request_time();
-
- if (uri != NULL && strncasecmp(uri, "http://", 7) == 0)
- vhost = "";
- else if (vhost == NULL)
- vhost = libnet_host_lookup(addr->daddr, Opt_dns);
-
- if (method != NULL && uri != NULL && vhost != NULL && reqtime != NULL) {
- printf("%s - %s [%s] \"%s %s%s%s\" - - \"%s\" \"%s\"\n",
- libnet_host_lookup(addr->saddr, Opt_dns),
- (user ? user : "-"), reqtime, method,
- (*vhost ? "http://" : vhost), vhost, uri,
- (referer ? referer : "-"), (agent ? agent : "-"));
- }
- }
- return (discard);
- }
-
- void
- sniff_http_client(struct tcp_stream *ts, void **yoda)
- {
- int i;
-
- /* Only handle HTTP client traffic. */
- if (ts->addr.dest != 80 && ts->addr.dest != 3128 && ts->addr.dest != 8080)
- return;
-
- switch (ts->nids_state) {
- case NIDS_JUST_EST:
- /* Collect data. */
- ts->server.collect = 1;
-
- case NIDS_DATA:
- if (ts->server.count_new != 0) {
- i = process_http_request(&ts->addr, ts->server.data,
- ts->server.count - ts->server.offset);
- nids_discard(ts, i);
- }
- break;
-
- default:
- if (ts->server.count != 0) {
- process_http_request(&ts->addr, ts->server.data,
- ts->server.count - ts->server.offset);
- }
- break;
- }
- }
-
- void
- null_syslog(int type, int errnum, struct ip *iph, void *data)
- {
- }
-
- int
- main(int argc, char *argv[])
- {
- int c;
-
- while ((c = getopt(argc, argv, "i:nh?V")) != -1) {
- switch (c) {
- case 'i':
- nids_params.device = optarg;
- break;
- case 'n':
- Opt_dns = 0;
- break;
- case 'V':
- fprintf(stderr, "Version: %s\n", VERSION);
- usage();
- break;
- default:
- usage();
- }
- }
- argc -= optind;
- argv += optind;
-
- if (argc != 0)
- usage();
-
- nids_params.scan_num_hosts = 0;
- nids_params.syslog = null_syslog;
-
- if (!nids_init()) {
- fprintf (stderr, "%s\n", nids_errbuf);
- exit(1);
- }
- nids_register_tcp(sniff_http_client);
-
- nids_run();
-
- /* NOTREACHED */
-
- exit(0);
- }
-
- /* 5000. */
-